#include "bsp_adc.h"
#include "config.h"

ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2;
ADC_HandleTypeDef hadc3;
DMA_HandleTypeDef hdma_adc1;
DMA_HandleTypeDef hdma_adc2;
DMA_HandleTypeDef hdma_adc3;

__packed struct ADC_PIN {
    ADC_HandleTypeDef *hadc;
    DMA_HandleTypeDef *hdma_adc;
    ADC_TypeDef *adc;
    uint32_t channel;
    GPIO_TypeDef *GPIO;
    uint32_t PIN;
    DMA_Stream_TypeDef *DMA_Stream;
    uint32_t DMA_Channel;
    IRQn_Type irq_type;
    uint8_t flag;
};
typedef struct ADC_PIN ADC_Struct;
struct __ADC_DEV {
   struct rt_device dev;
    GPIO_TypeDef *GPIO;
    uint32_t PIN;
    ADC_TypeDef *adc;
    uint16_t rank;
};

typedef struct __ADC_DEV ADC_DEV;
ADC_Struct ADC_PAR[]= {
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_0,GPIOA,GPIO_PIN_0,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_1,GPIOA,GPIO_PIN_1,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_2,GPIOA,GPIO_PIN_2,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_3,GPIOA,GPIO_PIN_3,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_4,GPIOA,GPIO_PIN_4,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_5,GPIOA,GPIO_PIN_5,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_6,GPIOA,GPIO_PIN_6,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_7,GPIOA,GPIO_PIN_7,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_8,GPIOB,GPIO_PIN_0,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_9,GPIOB,GPIO_PIN_1,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_10,GPIOC,GPIO_PIN_0,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_11,GPIOC,GPIO_PIN_1,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_12,GPIOC,GPIO_PIN_2,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_13,GPIOC,GPIO_PIN_3,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_14,GPIOC,GPIO_PIN_4,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},
    {&hadc1,&hdma_adc1,ADC1,ADC_CHANNEL_15,GPIOC,GPIO_PIN_5,DMA2_Stream0,DMA_CHANNEL_0,DMA2_Stream0_IRQn,0},

    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_0,GPIOA,GPIO_PIN_0,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_1,GPIOA,GPIO_PIN_1,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_2,GPIOA,GPIO_PIN_2,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_3,GPIOA,GPIO_PIN_3,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_4,GPIOA,GPIO_PIN_4,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_5,GPIOA,GPIO_PIN_5,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_6,GPIOA,GPIO_PIN_6,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_7,GPIOA,GPIO_PIN_7,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_8,GPIOB,GPIO_PIN_0,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_9,GPIOB,GPIO_PIN_1,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_10,GPIOC,GPIO_PIN_0,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_11,GPIOC,GPIO_PIN_1,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_12,GPIOC,GPIO_PIN_2,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_13,GPIOC,GPIO_PIN_3,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_14,GPIOC,GPIO_PIN_4,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},
    {&hadc2,&hdma_adc2,ADC2,ADC_CHANNEL_15,GPIOC,GPIO_PIN_5,DMA2_Stream2,DMA_CHANNEL_1,DMA2_Stream2_IRQn,0},

    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_0,GPIOA,GPIO_PIN_0,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_1,GPIOA,GPIO_PIN_1,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_2,GPIOA,GPIO_PIN_2,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_3,GPIOA,GPIO_PIN_3,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_4,GPIOF,GPIO_PIN_6,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_5,GPIOF,GPIO_PIN_7,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_6,GPIOF,GPIO_PIN_8,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_7,GPIOF,GPIO_PIN_9,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_8,GPIOF,GPIO_PIN_10,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_9,GPIOF,GPIO_PIN_3,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_10,GPIOC,GPIO_PIN_0,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_11,GPIOC,GPIO_PIN_1,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_12,GPIOC,GPIO_PIN_2,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_13,GPIOC,GPIO_PIN_3,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_14,GPIOF,GPIO_PIN_4,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
    {&hadc3,&hdma_adc3,ADC3,ADC_CHANNEL_15,GPIOF,GPIO_PIN_5,DMA2_Stream1,DMA_CHANNEL_1,DMA2_Stream1_IRQn,0},
};
#define ADC_NUM1 (sizeof(ADC_PAR)/sizeof(struct ADC_PIN))
int Get_ADC_index(ADC_DEV *adc_dev)
{
    int i=0;
    for(i=0; i<ADC_NUM1; i++)
    {
        if(adc_dev->adc==ADC_PAR[i].adc&&adc_dev->GPIO==ADC_PAR[i].GPIO&&adc_dev->PIN==ADC_PAR[i].PIN)
            return i;
    }
    return -1;
}

void MX_ADC_Init(ADC_DEV *adc_dev)
{
	int i=0;
    i=Get_ADC_index(adc_dev);
    ADC_ChannelConfTypeDef sConfig = {0};

    ADC_PAR[i].hadc->Instance = adc_dev->adc;
    ADC_PAR[i].hadc->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    ADC_PAR[i].hadc->Init.Resolution = ADC_RESOLUTION_12B;
    ADC_PAR[i].hadc->Init.ScanConvMode = ENABLE;
    ADC_PAR[i].hadc->Init.ContinuousConvMode = ENABLE;
    ADC_PAR[i].hadc->Init.DiscontinuousConvMode = DISABLE;
    ADC_PAR[i].hadc->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    ADC_PAR[i].hadc->Init.ExternalTrigConv = ADC_SOFTWARE_START;
    ADC_PAR[i].hadc->Init.DataAlign = ADC_DATAALIGN_RIGHT;
    ADC_PAR[i].hadc->Init.NbrOfConversion = 1;
    ADC_PAR[i].hadc->Init.DMAContinuousRequests = ENABLE;
    ADC_PAR[i].hadc->Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(ADC_PAR[i].hadc->Instance==ADC1)
    {
        __HAL_RCC_ADC1_CLK_ENABLE();
    }
    if(ADC_PAR[i].hadc->Instance==ADC2)
    {
        __HAL_RCC_ADC2_CLK_ENABLE();
    }
    if(ADC_PAR[i].hadc->Instance==ADC3)
    {
        __HAL_RCC_ADC3_CLK_ENABLE();
    }
    if(ADC_PAR[i].GPIO==GPIOA)
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();
    }
    if(ADC_PAR[i].GPIO==GPIOB)
    {
        __HAL_RCC_GPIOB_CLK_ENABLE();
    }
    if(ADC_PAR[i].GPIO==GPIOC)
    {
        __HAL_RCC_GPIOC_CLK_ENABLE();
    }
    if(ADC_PAR[i].GPIO==GPIOF)
    {
        __HAL_RCC_GPIOF_CLK_ENABLE();
    }
    GPIO_InitStruct.Pin = ADC_PAR[i].PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(ADC_PAR[i].GPIO, &GPIO_InitStruct);

    ADC_PAR[i].hdma_adc->Instance = ADC_PAR[i].DMA_Stream;
    ADC_PAR[i].hdma_adc->Init.Channel = ADC_PAR[i].DMA_Channel;
    ADC_PAR[i].hdma_adc->Init.Direction = DMA_PERIPH_TO_MEMORY;
    ADC_PAR[i].hdma_adc->Init.PeriphInc = DMA_PINC_DISABLE;
    ADC_PAR[i].hdma_adc->Init.MemInc = DMA_MINC_ENABLE;
    ADC_PAR[i].hdma_adc->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    ADC_PAR[i].hdma_adc->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    ADC_PAR[i].hdma_adc->Init.Mode = DMA_CIRCULAR;
    ADC_PAR[i].hdma_adc->Init.Priority = DMA_PRIORITY_LOW;
    ADC_PAR[i].hdma_adc->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(ADC_PAR[i].hdma_adc) != HAL_OK)
    {
        Error_Handler();
    }

    __HAL_LINKDMA(ADC_PAR[i].hadc,DMA_Handle,*ADC_PAR[i].hdma_adc);


    if (HAL_ADC_Init(ADC_PAR[i].hadc) != HAL_OK)
    {
        Error_Handler();
    }

    sConfig.Channel = ADC_PAR[i].channel;
    sConfig.Rank = adc_dev->rank;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    if (HAL_ADC_ConfigChannel(ADC_PAR[i].hadc, &sConfig) != HAL_OK)
    {
        Error_Handler();
    }
}

/**
* @brief ADC MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hadc: ADC handle pointer
* @retval None
*/
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
    ADC_Struct *adc_struct;
    adc_struct = (ADC_Struct*)rt_container_of(hadc,struct ADC_PIN,hadc);
    if(adc_struct->hadc->Instance==ADC1)
    {
        __HAL_RCC_ADC1_CLK_DISABLE();
    }
    else if(adc_struct->hadc->Instance==ADC2)
    {
        __HAL_RCC_ADC2_CLK_DISABLE();
    }
    else if(adc_struct->hadc->Instance==ADC3)
    {
        __HAL_RCC_ADC3_CLK_DISABLE();
    }
    if(adc_struct->GPIO==GPIOA)
        __HAL_RCC_GPIOA_CLK_DISABLE();
    else if(adc_struct->GPIO==GPIOB)
        __HAL_RCC_GPIOB_CLK_DISABLE();
    else if(adc_struct->GPIO==GPIOC)
        __HAL_RCC_GPIOC_CLK_DISABLE();
    else if(adc_struct->GPIO==GPIOF)
        __HAL_RCC_GPIOF_CLK_DISABLE();

    HAL_GPIO_DeInit(adc_struct->GPIO, adc_struct->PIN);
    HAL_DMA_DeInit(adc_struct->hdma_adc);
}
void MX_ADC_DMA_Init(ADC_DEV *adc_dev)
{
    int i=0;
    i=Get_ADC_index(adc_dev);
    if(i==-1) return;
    if(ADC_PAR[i].DMA_Stream>=DMA1_Stream0&&ADC_PAR[i].DMA_Stream<=DMA1_Stream7)
    {
        __HAL_RCC_DMA1_CLK_ENABLE();
    }/* DMA controller clock enable */
    else if(ADC_PAR[i].DMA_Stream>=DMA2_Stream0&&ADC_PAR[i].DMA_Stream<=DMA2_Stream7)
    {
        __HAL_RCC_DMA2_CLK_ENABLE();
    }
    HAL_NVIC_SetPriority(ADC_PAR[i].irq_type, 0, 0);
    HAL_NVIC_EnableIRQ(ADC_PAR[i].irq_type);
}

void DMA2_Stream0_IRQHandler(void)
{
    rt_interrupt_enter();
    HAL_DMA_IRQHandler(&hdma_adc1);
    rt_interrupt_leave();
}

void DMA2_Stream1_IRQHandler(void)
{
    rt_interrupt_enter();
    HAL_DMA_IRQHandler(&hdma_adc3);
    rt_interrupt_leave();
}
void DMA2_Stream2_IRQHandler(void)
{
    rt_interrupt_enter();
    HAL_DMA_IRQHandler(&hdma_adc2);
    rt_interrupt_leave();
}
uint16_t *collect_value;
rt_err_t adc_dev_open(struct rt_device *Device, rt_uint16_t oflag)
{
	
	int i=0;
    ADC_DEV* adc_dev;
    adc_dev = (ADC_DEV*)rt_container_of(Device,struct __ADC_DEV,dev);
	collect_value=rt_malloc(sizeof(uint16_t)*adc_dev->rank);
    i=Get_ADC_index(adc_dev);
    if(i==-1)
	{
		rt_free(collect_value);
		return false;
	}
	 
    MX_ADC_DMA_Init(adc_dev);
    MX_ADC_Init(adc_dev);
    HAL_ADC_Start_DMA(ADC_PAR[i].hadc,(uint32_t*)collect_value,adc_dev->rank);
	 
    return true;
}

rt_size_t adc_dev_read(struct rt_device *Device,
						rt_off_t offest,
						void *buf,
						rt_size_t len)
{
	 
	uint16_t vlaue=0;
	vlaue=collect_value[offest]*3.3*100/4096;
	*(uint16_t *)buf= vlaue;
	 
    return true;
}

rt_err_t adc_dev_close(struct rt_device *Device)
{
	 
	rt_free(collect_value);
    ADC_DEV* adc_dev;
    adc_dev = (ADC_DEV*)rt_container_of(Device,struct __ADC_DEV,dev);
    HAL_ADC_Stop_DMA(ADC_PAR[Get_ADC_index(adc_dev)].hadc);
    HAL_ADC_MspDeInit(ADC_PAR[Get_ADC_index(adc_dev)].hadc);
	 
    return RT_EOK;
}
ADC_DEV  ADC1_collect= {0};
int adc_register()
{
	
    ADC1_collect.GPIO=GPIOA;
    ADC1_collect.PIN=GPIO_PIN_5;
    ADC1_collect.adc=ADC1;
    ADC1_collect.rank=1;
    ADC1_collect.dev.close=adc_dev_close;
    ADC1_collect.dev.open=adc_dev_open;
    ADC1_collect.dev.read=adc_dev_read;
    return rt_device_register(&ADC1_collect.dev,"adc",RT_DEVICE_FLAG_RDWR);   
}

DEVICE_INIT(adc_register);


int read_adc_value(uint8_t argc, char **argv)
{
	rt_device_t dev=rt_device_find("adc");
	uint16_t buf;
	int val=0;
	rt_device_read(dev,0,(uint8_t*)&buf,0);
	val=buf;
	rt_kprintf("adc[%d] value is %d.%dV\r\n",0,val/100,val%100);
	return true;
}
MSH_CMD_EXPORT(read_adc_value,read adc value);





